package com.cskaoyan.javase.oop1._6constructor._0introduction;

import org.junit.Test;

import java.nio.channels.Pipe;

/**
 * 创建一个教师类，有课程和年龄两个属性，行为是可以上课。
 * 现在我们需要创建以下对象：
 * 18岁的Java老师对象
 * 28岁的C++老师对象
 * 30岁的Python老师对象
 * ...
 * 按照之前我们的做法，需要先创建出对象，再进行成员变量的赋值。
 * 这样做如果只有一个两个对象还好，如果需要创建很多对象，就有点过于麻烦了。
 * 对象的属性，能不能"出厂"的时候就设定好呢？
 * 有这种需求时，就需要，构造方法（constructor，也叫构造器）来完成了。
 *
 * 构造器(方法)的语法:
 * 语法结构和一般方法不同，如下：
 *
 * [访问权限修饰符] 类名(形参列表){
 *   // 构造方法体
 * }
 *      解释:
 *      1.访问权限修饰符还没学,所以今天我们默认这里写public
 *          当然访问权限修饰符是可以不写的,是可以省略的
 *
 *      2.紧跟访问权限修饰符的后面,必须写"类名"
 *          这个类名可以认为是构造器的名字
 *          也就是说构造器的名字必须和类名保持一致
 *          --> 构造器的名字也是大驼峰的,这一点和普通方法就不同了
 *          注意这个"类名"不是构造方法的返回值类型
 *          构造方法没有返回值,也不需要返回值,构造器中也不能使用return
 *
 *      3.形参列表,方法体和普通方法没有太大区别,稍微需要注意的是
 *          构造方法的方法体类似于成员方法的方法体
 *          因为它们都可以使用this关键字
 *
 * 构造器的作用(非常重要):
 *      构造器是用来new创建对象的(这是一个非常错误的观点)
 *      (重点)在Java中使用new关键字创建某类的对象，必然调用该类的构造方法。但构造器的作用不是创建对象，而是在new对象的过程中用来给成员变量赋值的。构造器的作用是给成员变量赋值！
 *      解释:
 *      1.构造器不是普通方法,它也无法通过普通方法的调用方式去调用,它是在new对象过程中,由JVM主动去调用的一个方法,程序员是没有办法主动调用这个方法的.
 *
 *      2.程序员虽然不能主动调用构造器,但是可以指示JVM在创建对象时调用哪个构造器给成员变量赋值
 *      使用的语法格式就是:
 *      类名 对象名 = new 类名(实参列表);
 *      根据实参列表的不同,可能调用不同的构造器(这是方法的重载)
 *
 * 在类中定义构造器:
 *      1.在一个类中,如果没有手动定义任何构造器,那么会由编译器在编译该类代码时,为该类加上无参构造器
 *      这种无参构造器,一般称之为"默认无参(构造器)"
 *      默认无参的格式是:
 *      [访问权限修饰符] 类名(){ }
 *      推论:
 *          a.在Java中,一个类必然有构造器
 *          b.(建议)建议在定义一个需要new对象的类时
 *              考虑给该类手动添加无参构造器
 *
 *      2.无参构造器是没有办法主动给成员变量赋值,所以还需要有参构造器,来给成员变量赋值
 *      有参构造器的格式:
 *      [访问权限修饰符] 类名(数据类型 成员变量名1,数据类型 成员变量名2...){
 *          this.成员变量名1 = 成员变量名1;
 *          this.成员变量名2 = 成员变量名2;
 *          ...
 *      }
 *
 *      3.一个类中可以允许定义多个构造器,这些构造器之间是方法重载的关系.
 *
 *      4.以上默认无参构造器:
 *          [访问权限修饰符] 类名(){ }
 *        以及有参构造器:
 *           [访问权限修饰符] 类名(数据类型 成员变量名1,数据类型 成员变量名2...){
 *              this.成员变量名1 = 成员变量名1;
 *              this.成员变量名2 = 成员变量名2;
 *              ...
 *           }
 *        它们的语法格式都是非常固定的,我们一般称它们为"标准格式构造器"
 *        标准格式的构造器,可以直接用快捷键"alt + insert"生成
 *        这个快捷键很常用,用于生成Java代码中固定格式的代码
 *
 *
 * @since 09:32
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    @Test
    public void test() {
        // 18岁的Java老师对象
        /*Teacher t1 = new Teacher();
        t1.course = "Java";
        t1.age = 18;
        t1.teach();
        // 28岁的C++老师对象
        Teacher t2 = new Teacher();
        t2.course = "C++";
        t2.age = 28;
        t2.teach();
        // 30岁的Python老师对象
        Teacher t3 = new Teacher();
        t3.course = "Python";
        t3.age = 38;
        t3.teach();*/
    }

    @Test
    public void test2() {
        Teacher t1 = new Teacher("数学");
        System.out.println(t1.course);

        Teacher t2 = new Teacher("物理", 50);
        t2.teach();
    }

}

class Teacher {
    String name;
    String course;
    int age;

    public void teach() {
        System.out.println(age + "岁的" + course + "老师,正在上课!");
    }

    // 定义有参构造器,给course赋值,单参构造器
    public Teacher(String course) {
        this.course = course;
    }

    // 定义有参构造器,给age和course赋值,双参构造器
    public Teacher(String course, int age) {
        this.course = course;
        this.age = age;
    }

    // 默认无参构造器
    public Teacher() {
    }

    // 单参age构造器
    public Teacher(int age) {
        this.age = age;
    }


}

class A {
}